import datetime
import os
import uuid

from fastapi import APIRouter, Depends, HTTPException, Request, UploadFile, File
from sqlalchemy.orm import Session
from database import get_db
from schemas.token import UserCreate, Token, UserInfo, ChangePassword, UserLogin
from models.user import User
from setting import BASE_DIR, MAX_FILE_SIZE_MB, AVATAR_DIR, ACCESS_TOKEN_EXPIRE_MINUTES
from utils.response_utils import make_response
from utils.time_stamp_verifier import is_valid_timestamp_ts
from utils.token_utils import hash_password, verify_password, create_access_token, get_current_user
from datetime import timedelta
from utils.log_utils import logger

router = APIRouter(
    prefix="/api/user/v1",  # 所有路由的前缀
    tags=["用户管理模块"],  # 文档中的标签
    responses={404: {"description": "Not found"}}  # 统一响应
)


@router.post("/register", summary="注册", response_model=dict, description="")
def register(user: UserCreate, db: Session = Depends(get_db)):
    if db.query(User).filter(User.username == user.username).first():
        raise HTTPException(status_code=400, detail="用户名已存在")
    db_user = User(username=user.username, hashed_password=hash_password(user.password))
    db.add(db_user)
    db.commit()
    return {"code": 200, "message": "注册成功", "data": {}}


@router.post("/login",
             summary="登录",
             response_model=Token,
             description="登录接口，username，password，time需要格式正确（13位）、"
                         "校验位匹配（前12位相加，取首位下标拼接成第13位时间戳）、未过期（3分钟）")
def login(user: UserLogin, request: Request, db: Session = Depends(get_db)):
    """
    """
    if not is_valid_timestamp_ts(user.time):
        return make_response(400, "用户名或密码错误")

    db_user = db.query(User).filter(User.username == user.username).first()
    if not db_user or not verify_password(user.password, db_user.hashed_password):
        return make_response(400, "用户名或密码错误")

    # 记录上传登录时间，累计登录次数，登录ip
    db_user.last_login_time = datetime.datetime.utcnow()
    db_user.login_count = (db_user.login_count or 0) + 1  # 累加登录次数
    db_user.last_login_ip = request.headers.get("x-forwarded-for", request.client.host)
    db.commit()

    token = create_access_token({"sub": db_user.username, "id": db_user.id},
                                expires_delta=timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES))
    return make_response(200, "登录成功", {"access_token": token})


@router.get("/userinfo", summary="查询用户信息")
def userinfo(current_user: User = Depends(get_current_user)):
    r = UserInfo(
        username=current_user.username,
        create_time=current_user.create_time,
        last_login_time=current_user.last_login_time,
        login_count=current_user.login_count,
        last_login_ip=current_user.last_login_ip,
        role=current_user.role,
        bio=current_user.bio,
        avatar=current_user.avatar,
    )

    return {"code": 200, "message": "查询用户信息成功", "data": r.model_dump()}


@router.post("/upload_avatar", summary="上传头像", response_model=dict)
def upload_avatar(
        file: UploadFile = File(...),
        db: Session = Depends(get_db),
        current_user: User = Depends(get_current_user),
):
    # 访问路径 host/media/avatars/91a918e8eaf24543a7bcb5d179bfc6c3.jpeg
    # 1. 验证文件类型
    if file.content_type not in ["image/jpeg", "image/png"]:
        return {"code": 400, "message": "只支持 JPG 或 PNG 格式", "data": {}}

    # 2. 读取内容以判断大小（可选）
    contents = file.file.read()
    file_size = len(contents)
    if file_size > MAX_FILE_SIZE_MB * 1024 * 1024:
        return {"code": 400, "message": "文件大小不能超过2MB", "data": {}}

    # 3. 获取扩展名
    ext = os.path.splitext(file.filename)[1].lower()
    if ext not in [".jpg", ".jpeg", ".png"]:
        return {"code": 400, "message": "扩展名无效", "data": {}}
    # 4. 文件名命名方式: 用户ID + uuid
    filename = f"{current_user.id}_{uuid.uuid4().hex}{ext}"
    file_path = AVATAR_DIR / filename

    # 5. 清除旧头像（如果有且是本地文件）
    if current_user.avatar and current_user.avatar.startswith("/media/avatars/"):
        old_file = BASE_DIR / current_user.avatar.lstrip("/")
        if old_file.exists():
            try:
                old_file.unlink()
            except Exception as e:
                logger.error(f"删除本地头像失败{e}")

    # 6. 写入新文件
    with open(file_path, "wb") as f:
        f.write(contents)

    # 7. 更新数据库中的 avatar
    current_user.avatar = f"/media/avatars/{filename}"
    db.commit()

    return {
        "code": 200,
        "message": "上传成功",
        "data": {"avatar": current_user.avatar}
    }


@router.post("/change_password", response_model=dict, summary="修改当前用户密码")
def change_password(
        data: ChangePassword,
        db: Session = Depends(get_db),
        current_user: User = Depends(get_current_user)
):
    """
    修改当前登录用户的密码。需携带有效 JWT Token。
    请求体包含旧密码和新密码。
    """
    # 1. 验证旧密码是否正确
    if not verify_password(data.old_password, current_user.hashed_password):
        return {"code": 400, "message": "旧密码不正确", "data": {}}

    # 2. 可选：检查新密码与旧密码是否相同
    if verify_password(data.new_password, current_user.hashed_password):
        return {"code": 400, "message": "新密码不能与旧密码相同", "data": {}}

    # 3. 进一步可加密码强度校验（如必须包含数字、字母等），根据项目需求自行扩展

    # 4. 哈希新密码并更新到数据库
    new_hashed = hash_password(data.new_password)
    current_user.hashed_password = new_hashed
    try:
        # 如果 last_password_change 是 DateTime 类型
        current_user.last_password_change = datetime.datetime.utcnow()
    except Exception as e:
        logger.error(e)

    # 5. 提交事务
    db.commit()
    return {"code": 200, "message": "密码修改成功", "data": {}}


@router.post("/logout", summary="退出登录", response_model=dict)
def logout(_=Depends(get_current_user)):
    return {"code": 200, "message": "注销成功", "data": {}}
